#include "StepByStep.h"

void FreeValueList(ValueList *VL)
{
  VList *Pt, *Pt1;

  for (Pt = VL->List; Pt != NULL; Pt = Pt1) {
    Pt1 = Pt->next; free(Pt);
  }

  VL->List = NULL;
  VL->NumValue = 0;
}

void FreeTokenList(TokenList *Pt)
{
  TokenList *Pt1;

  while (Pt != NULL) {
    Pt1 = Pt->next;
    FreeValueList(&(Pt->VList)); free(Pt);
    Pt = Pt1;
  }
}

void FreeTypeList(StringList *Pt)
{
  StringList *Pt1;

  while (Pt != NULL) { Pt1 = Pt->next; free(Pt); Pt = Pt1; }
}

void FreeTypedList(TypedList *Pt)
{
  TypedList *Pt1;

  while (Pt != NULL) {
    Pt1 = Pt->next;
    FreeTypeList(Pt->Type); FreeValueList(&(Pt->VList)); free(Pt);
    Pt = Pt1;
  }
}

void FreeTypedArray(int Num, TypedList *Para)
{
  TypedList *Pt;
  int        i;

  Pt = Para;
  for (i = 0; i < Num; i++, Pt++) {
    FreeTypeList(Pt->Type);
    FreeValueList(&(Pt->VList));
  }
  free(Para);
}

void FreePENodeList(PENode *Pt)
{
  PENode *Pt1;

  if (Pt == NULL) return;

  if (Pt->Type != ATOM) { Pt1 = Pt; Pt = Pt->sons; free(Pt1); }
  while (Pt != NULL) {
    Pt1 = Pt->next;
    if (Pt->Vars != NULL) FreeTypedList(Pt->Vars);
    if (Pt->Pred != NULL) FreeTokenList(Pt->Pred);
    if (Pt->sons != NULL) FreePENodeList(Pt->sons);
    free(Pt);
    Pt = Pt1;
  }
}

void FreeOneAction(ActionList *Act)
{
  FreeTypedArray(Act->NumPara, Act->Para);
  FreePENodeList(Act->PC);
  FreePENodeList(Act->Effect);
  free(Act);
}

void FreePCList(PredKnowledge *PC)
{
  PredKnowledge *PC1;

  while (PC != NULL) {
    PC1 = PC->next;
    FreeTypedArray(NumParaOfPred(PC->PredNo), PC->Para);
    free(PC);
    PC = PC1;
  }
}

void FreeEffectList(PENode *PE)
{
  PENode *PE1;

  for ( ; PE != NULL; PE = PE1) {
    PE1 = PE->next;
    FreeTokenList(PE->Pred);  free(PE);
  }
}

void FreeActKnowledge(ActKnowledge *ActK)
{
  PredKnowledge *PC, *PC1;
#ifdef WHEN_CLAUSE
  PENode        *PE, *PE1;
#endif

  for (PC = ActK->PC; PC != NULL; PC = PC1) {  // Free all PCs
    PC1 = PC->next;
    FreePredKnowledge(PC);  free(PC);
  }

  FreeEffectList(ActK->Effect);  // Free all Effects

#ifdef WHEN_CLAUSE
  for (PE = ActK->CondEffect; PE != NULL; PE = PE1) {  // Free all When Clauses
    PE1 = PE->next;

    FreeTokenList(PE->sons->Pred);  free(PE->sons);
    FreeEffectList(PE->Effect);

    free(PE);
  }
#endif

  FreeTypedArray(NumParaOfAct(ActK->ActNo), ActK->Para);
  free(ActK);
}

void FreeActionsOfPred(PredKnowledge *Pred)
{
  ActKnowledge *ActK, *ActK1;
  TypedList    *Para;
  int          i;

  for (ActK = Pred->Act; ActK != NULL; ActK = ActK1) {
    ActK1 = ActK->next;
    FreeActKnowledge(ActK);
  }

  Para = Pred->Para + NumParaOfPred(Pred->PredNo);
  for (i = 0; i < Pred->NumEP; i++,Para++)
    FreeValueList(&(Para->VList));

  FreePCList(Pred->CPC);
  FreeEffectList(Pred->CEffect);

  Pred->NumAct = 0;
  Pred->CPC = NULL;
  Pred->Act = NULL;  Pred->CEffect = NULL;
}

void FreePredKnowledge(PredKnowledge *Pd)
{
  FreeActionsOfPred(Pd);
  FreeTypedArray(NumParaOfPred(Pd->PredNo)+Pd->NumEP, Pd->Para);

  FreePCList(Pd->CPC);  // Free Common Info of Pd;
  FreeEffectList(Pd->CEffect);

  Pd->PAct = NULL;
  Pd->Para = NULL;
}

void FreeDomainOneLaw(DomainLaw *law)
{
  PCOfLaw *PC, *PC1;

  for (PC = law->PCLaw; PC != NULL; PC = PC1) {
    PC1 = PC->next;
    FreeTokenList(PC->Pred);  free(PC);
  }

  FreeTokenList(law->Pred1);
  FreeTokenList(law->Pred2);
  FreeTypedArray(law->NumPara, law->Para);

  for (PC = law->PC; PC != NULL; PC = PC1) {
    PC1 = PC->next;
    FreeTokenList(PC->Pred);  free(PC);
  }

  free(law);
}

// Free all memory for Goal State
void FreeMemoryOfGoalState()
{
  PredFact *Pt, *Pt1;
  int      i;

  // Free Object Memory
  FreeTypedArray(NumObject, Objects);

  // Free Fact Memory
  for (i = 0; i < NumPred; i++)
    for (Pt = State[i].List; Pt != NULL; Pt = Pt1) {
      Pt1 = Pt->next;
      FreeTokenList(Pt->Para);  free(Pt);
    }
  free(State);
}

void FreePKTree(PKTree *Pk)
{
  PredKnowledge *PC, *PC1;

  FreePredKnowledge(Pk->Pred);
  free(Pk->Pred);

  for (PC = Pk->PC; PC != NULL; PC = PC1) {
     PC1 = PC->next;
     FreeTypedArray(NumParaOfPred(PC->PredNo), PC->Para);
     free(PC);
  }

  free(Pk);
}

void FreeDomainMemory()
{
  DomainAxiom *pAxiom;
  SafetyStru  *PSafe;
  StringList  *Pt1, *Pt2;
  DomainLaw   *law1, *law2;
  PredList    *Pt3;
  PENode      *PE, *PE1;
  PKTree      *Pk, *Pk1;
  int          i;

  // Free Axiom Memory
  while (Axioms != NULL) {
    pAxiom = Axioms->next;
    FreeTypedArray(Axioms->NumPara, Axioms->Vars);
    FreePENodeList(Axioms->Context);
    FreePENodeList(Axioms->Imply);
    free(Axioms);
    Axioms = pAxiom;
  }

  // Free Safety Memory
  while (Safe != NULL) {
    PSafe = Safe->next;
    FreeTypedArray(Safe->NumPara, Safe->Vars);

    for (PE = Safe->sons; PE != NULL; PE = PE1) {
      PE1 = PE->next;
      FreeTokenList(PE->Pred);  free(PE);
    }

    free(Safe);
    Safe = PSafe;
  }

  // Free Domain Knowledge
  for (i = 0; i < NumPred; i++) {
    for (Pk = (PK+i)->next; Pk != NULL; Pk = Pk1) {
      Pk1 = Pk->next;
      FreePKTree(Pk);
    }

    for (Pk = (nPK+i)->next; Pk != NULL; Pk = Pk1) {
      Pk1 = Pk->next;
      FreePKTree(Pk);
    }
  }
  free(PK);   free(nPK);

  // Free Domain Law
  for (i = 0; i < NumPred; i++) {
    for (law1 = (Law0+i)->next; law1 != NULL; law1 = law2) {
      law2 = law1->next;
      FreeDomainOneLaw(law1);
    }
    for (law1 = (Law1+i)->next; law1 != NULL; law1 = law2) {
      law2 = law1->next;
      FreeDomainOneLaw(law1);
    }
    for (law1 = (Law3+i)->next; law1 != NULL; law1 = law2) {
      law2 = law1->next;
      FreeDomainOneLaw(law1);
    }
  }
  free(Law0);  free(Law1);  free(Law3);

  for (Pt1 = Require; Pt1 != NULL; Pt1 = Pt2) {
    Pt2 = Pt1->next;
    free(Pt1);
  }

  FreeTypedArray(NumConstant, Constants);
  FreeTypedList(Type);

  // Free Predication in Domain
  Pt3 = Predication;
  for (i = 0; i < NumPred; i++,Pt3++) FreeTypedArray(Pt3->NumPara, Pt3->Para);
  free(Predication);

  // Free Domain Action
  for (i = 0; i < NumAct; i++) FreeOneAction((Action+i)->next);
  free(Action);
}
